package cn.blnp.net.flowable.boot.localize.i18n;

import cn.blnp.net.flowable.boot.service.TaskRecallService;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.*;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.repository.ProcessDefinitionQuery;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.TaskQuery;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

/**
 * <h3></h3>
 *
 * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
 * @version 1.0
 * @since 2025/6/20 16:26
 */
@Slf4j
@SpringBootTest
public class I18nFlowTest {

    @Resource
    private RepositoryService repositoryService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private IdentityService identityService;
    @Resource
    private TaskService taskService;
    @Resource
    private HistoryService historyService;
    @Resource
    private TaskRecallService taskRecallService;
    @Resource
    private DynamicBpmnService dynamicBpmnService;

    /**
     *  <h2>多语种流程案例演示</h2>
     *  <ul>
     *      <li><b>流程定义文件：</b>{@link flow/localizationProcess.bpmn20.xml}</li>
     *      <li>
     *          <b>流程预览图：</b></br>
     *          <img src="https://cdn4.winhlb.com/2025/06/19/685369e3e128e.png" >
     *      </li>
     *  </ul>
     **/
    @Test
    public void test() {
        Deployment deploy = repositoryService.createDeployment()
                .addClasspathResource("flow/localizationProcess.bpmn20.xml")
                .name("多语种国际化支持")
                .deploy();
        log.info("部署ID：{}", deploy.getId());
        //流程定义信息
        ProcessDefinition procDef = repositoryService.createProcessDefinitionQuery()
                .deploymentId(deploy.getId())
                .singleResult();
        log.info("流程定义ID：{}", procDef.getId());
        log.info("默认流程名称：{}，描述：{}", procDef.getName(), procDef.getDescription());
        //查询各语言版本流程名称和描述
        procDef = queryProcessDefinition(procDef.getId(), "en");
        log.info("en版流程名称：{}，描述：{}", procDef.getName(), procDef.getDescription());
        procDef = queryProcessDefinition(procDef.getId(), "fr");
        log.info("fr版流程名称：{}，描述：{}", procDef.getName(), procDef.getDescription());

        //启动流程实例
        ProcessInstance procInst = runtimeService.startProcessInstanceById(procDef.getId());
        log.info("流程实例ID：{}", procInst.getId());
        //查询各语言版本任务名称和描述
        Task task = queryTask(procInst.getId(), null);
        log.info("默认任务名称:{}, 描述:{}", task.getName(), task.getDescription());
        task = queryTask(procInst.getId(), "en");
        log.info("en版任务名称:{}, 描述:{}", task.getName(), task.getDescription());
        task = queryTask(procInst.getId(), "fr");
        log.info("fr版任务名称:{}, 描述:{}", task.getName(), task.getDescription());
        ObjectNode infoNode = dynamicBpmnService
                .getProcessDefinitionInfo(procInst.getProcessDefinitionId());
        //修改法文版流程名称和描述
        dynamicBpmnService.changeLocalizationName("fr", procDef.getKey(),
                "Mise en ligne du système", infoNode);
        dynamicBpmnService.changeLocalizationDescription("fr", procDef.getKey(),
                "Ce lien est utilisé pour la mise en ligne du système d'exploitation humaine",
                infoNode);
        //添加韩文版流程名称和描述
        dynamicBpmnService.changeLocalizationName("ko", procDef.getKey(),
                "시스템 온라인 프로세스", infoNode);
        dynamicBpmnService.changeLocalizationDescription("ko", procDef.getKey(),
                "이것은 시스템 온라인에서의 수동 처리 과정입니다", infoNode);
        //添加韩文版任务名称和描述
        dynamicBpmnService.changeLocalizationName("ko", task.getTaskDefinitionKey(),
                "시스템 온라인", infoNode);
        dynamicBpmnService.changeLocalizationDescription("ko",
                task.getTaskDefinitionKey(),
                "이 단계는 인공 운영 시스템의 온라인 상태를 수동으로 조작하는 데 사용됩니다",
                infoNode);
        //保存
        dynamicBpmnService.saveProcessDefinitionInfo(procInst.getProcessDefinitionId(), infoNode);

        //查询各语言版本流程名称和描述
        procDef = queryProcessDefinition(procDef.getId(), "fr");
        log.info("修改后，fr版流程名称：{}，描述：{}", procDef.getName(), procDef.getDescription());
        procDef = queryProcessDefinition(procDef.getId(), "ko");
        log.info("ko版流程名称：{}，描述：{}", procDef.getName(), procDef.getDescription());
        //查询各语言版本任务名称和描述
        task = queryTask(procInst.getId(), "ko");
        log.info("ko版任务名称:{}, 描述:{}", task.getName(), task.getDescription());

        /**
         *  演示结果：
         **/
    }

    /**
     * <p><b>用途:查询流程定义信息<b></p>
     * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
     * @since 16:29 2025/6/20
     * @params [processDefinitionId, locale]
     * @param processDefinitionId
     * @param locale
     * @return org.flowable.engine.repository.ProcessDefinition
    **/
    private ProcessDefinition queryProcessDefinition(String processDefinitionId, String locale) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService
                .createProcessDefinitionQuery();
        if (StringUtils.isNotBlank(processDefinitionId)) {
            processDefinitionQuery.processDefinitionId(processDefinitionId);
        }
        if (StringUtils.isNotBlank(locale)) {
            processDefinitionQuery.locale(locale);
        }
        return processDefinitionQuery.singleResult();
    }

    /**
     * <p><b>用途:查询任务信息<b></p>
     * @author <a href="mailto:blnp.yibin@qq.com">lyb</a>
     * @since 16:30 2025/6/20
     * @params [processInstanceId, locale]
     * @param processInstanceId
     * @param locale
     * @return org.flowable.task.api.Task
    **/
    private Task queryTask(String processInstanceId, String locale) {
        TaskQuery taskQuery = taskService.createTaskQuery();
        if (StringUtils.isNotBlank(processInstanceId)) {
            taskQuery.processInstanceId(processInstanceId);
        }
        if (StringUtils.isNotBlank(locale)) {
            taskQuery.locale(locale);
        }
        return taskQuery.singleResult();
    }
}
